package com.boarsoft.common.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.common.Util;

public class InetUtil {
	private static final Logger log = LoggerFactory.getLogger(InetUtil.class);

	private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");

	private static InetAddress address;
	private static String ip;
	private static int port = 0;
	private static String addr;
	private static String hostName;

	static {
		init();
	}

	public static void init() {
		try {
			log.info("my.ens={}, my.host={}", System.getProperty("my.ens"), System.getProperty("my.host"));
			address = InetUtil.getLocalAddress(//
					System.getProperty("my.ens"), System.getProperty("my.host"));
			ip = address.getHostAddress();
			hostName = address.getHostName();
			port = Util.str2int(System.getProperty("my.port"), port);
			addr = new StringBuilder(ip).append(":").append(port).toString();
			log.info("My ip address is {}", addr);
		} catch (Exception e) {
			log.error("Error get default node addr", e);
		}
	}

	/**
	 * 获取网卡0的IP地址、缓存并返回
	 * 
	 * @param 网卡名，为空则取网卡0
	 * @param IP地址
	 * @return
	 * @throws SocketException
	 */
	public static InetAddress getLocalAddress(String ens, String host) throws SocketException {
		InetAddress addr = null;
		log.info("Lookup all network interface with {}/{}", ens, host);
		Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
		while (interfaces.hasMoreElements()) {
			NetworkInterface network = interfaces.nextElement();
			String nn = network.getName();
			log.debug("Lookup network interface {}", nn);
			Enumeration<InetAddress> addresses = network.getInetAddresses();
			if (addresses == null) {
				log.debug("Addresses of network interface {} is null", nn);
				continue;
			}
			if (Util.strIsNotEmpty(ens) && !nn.equalsIgnoreCase(ens)) {
				log.debug("Skip network interface {} == {}", nn, ens);
				continue;
			}
			while (addresses.hasMoreElements()) {
				InetAddress ia = addresses.nextElement();
				if (isValidAddress(ia)) {
					String a = ia.getHostAddress();
					String n = ia.getHostName();
					log.info("Find network = {}, hostname = {}, hostaddress = {}", nn, n, a);
					addr = ia;
					if (Util.strIsEmpty(host)) {
						continue;
					}
					if (n.startsWith(host) || a.startsWith(host)) {
						return ia;
					}
					if (n.matches(host) || a.matches(host)) {
						return ia;
					}
				}
			}
		}
		return addr;
	}

	/**
	 * 等同于 InetAddress.getLocalHost()，只是不抛异常
	 * 
	 * @return InetAddress，如果获取失败就返回null
	 */
	public static InetAddress getLocalHost() {
		try {
			return InetAddress.getLocalHost();
		} catch (UnknownHostException e) {
			log.error("Error on getLocalHost", e);
		}
		return null;
	}

	public static boolean isValidAddress(InetAddress address) {
		if (address == null || address.isLoopbackAddress())
			return false;
		String name = address.getHostAddress();
		return (name != null && !"0.0.0.0".equals(name) && !"127.0.0.1".equals(name)//
				&& IP_PATTERN.matcher(name).matches());
	}

	public static String getIp() {
		return ip;
	}

	public static int getPort() {
		return port;
	}

	public static String getHostName() {
		return hostName;
	}

	public static String getAddr() {
		return addr;
	}

	public static InetAddress getAddress() {
		return address;
	}
}
